package cc.shacocloud.kotlin.tools.http

import kotlinx.serialization.SerializationStrategy
import okhttp3.Interceptor
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor

/**
 * http 对象
 * @author 思追(shaco)
 */
object Http {

    val FORM_URLENCODED = "application/x-www-form-urlencoded;charset=utf-8".toMediaType()
    val APPLICATION_JSON = "application/json;charset=utf-8".toMediaType()
    val APPLICATION_XML = "application/xml;charset=utf-8".toMediaType()
    val TEXT_PLAIN = "text/plain;charset=utf-8".toMediaType()

    /**
     * 自定义请求方式
     */
    fun custom(
        url: String,
        method: String,
        headers: Map<String, String> = emptyMap(),
        level: HttpLoggingInterceptor.Level = HttpLoggingInterceptor.Level.HEADERS,
        interceptors: List<Interceptor> = emptyList(),
        httpClient: OkHttpClient = HttpClientBuilder.DEFAULT
    ): HttpClient {
        return HttpClient(url, method, httpClient)
            .logLevel(level)
            .headers(headers)
            .interceptors(interceptors)
    }

    /**
     * GET 请求
     */
    fun get(
        url: String,
        headers: Map<String, String> = emptyMap(),
        level: HttpLoggingInterceptor.Level = HttpLoggingInterceptor.Level.HEADERS,
        interceptors: List<Interceptor> = emptyList(),
        httpClient: OkHttpClient = HttpClientBuilder.DEFAULT
    ): HttpClient {
        return HttpClient(url, "GET", httpClient)
            .logLevel(level)
            .headers(headers)
            .interceptors(interceptors)
    }

    /**
     * POST formUrlencoded 请求
     */
    fun post(
        url: String,
        headers: Map<String, String> = emptyMap(),
        body: Map<String, String>,
        level: HttpLoggingInterceptor.Level = HttpLoggingInterceptor.Level.HEADERS,
        interceptors: List<Interceptor> = emptyList(),
        httpClient: OkHttpClient = HttpClientBuilder.DEFAULT
    ): HttpClient {
        return HttpClient(url, "POST", httpClient)
            .logLevel(level)
            .headers(headers)
            .formUrlencoded(body)
            .interceptors(interceptors)
    }

    /**
     * POST multipart/form-data 请求
     */
    fun postMultipart(
        url: String,
        headers: Map<String, String> = emptyMap(),
        body: Map<String, Any>,
        level: HttpLoggingInterceptor.Level = HttpLoggingInterceptor.Level.HEADERS,
        interceptors: List<Interceptor> = emptyList(),
        httpClient: OkHttpClient = HttpClientBuilder.DEFAULT
    ): HttpClient {
        return HttpClient(url, "POST", httpClient)
            .logLevel(level)
            .headers(headers)
            .formParams(body)
            .interceptors(interceptors)
    }

    /**
     * POST json 请求
     */
    fun postJson(
        url: String,
        headers: Map<String, String> = emptyMap(),
        body: Any,
        level: HttpLoggingInterceptor.Level = HttpLoggingInterceptor.Level.HEADERS,
        interceptors: List<Interceptor> = emptyList(),
        httpClient: OkHttpClient = HttpClientBuilder.DEFAULT
    ): HttpClient {
        return HttpClient(url, "POST", httpClient)
            .logLevel(level)
            .headers(headers)
            .applicationJson(body)
            .interceptors(interceptors)
    }

    /**
     * POST json 请求
     *
     * 使用 [kotlinx.serialization](https://github.com/Kotlin/kotlinx.serialization) 实现的 json 序列化
     */
    fun <T> postJson(
        url: String,
        headers: Map<String, String> = emptyMap(),
        serializer: SerializationStrategy<T>,
        body: T,
        level: HttpLoggingInterceptor.Level = HttpLoggingInterceptor.Level.HEADERS,
        interceptors: List<Interceptor> = emptyList(),
        httpClient: OkHttpClient = HttpClientBuilder.DEFAULT
    ): HttpClient {
        return HttpClient(url, "POST", httpClient)
            .logLevel(level)
            .headers(headers)
            .applicationJson(serializer, body)
            .interceptors(interceptors)
    }

    /**
     * PUT 请求
     */
    fun putJson(
        url: String,
        headers: Map<String, String> = emptyMap(),
        body: Any,
        level: HttpLoggingInterceptor.Level = HttpLoggingInterceptor.Level.HEADERS,
        interceptors: List<Interceptor> = emptyList(),
        httpClient: OkHttpClient = HttpClientBuilder.DEFAULT
    ): HttpClient {
        return HttpClient(url, "PUT", httpClient)
            .logLevel(level)
            .headers(headers)
            .applicationJson(body)
            .interceptors(interceptors)
    }

    /**
     * PUT 请求
     *
     * 使用 [kotlinx.serialization](https://github.com/Kotlin/kotlinx.serialization) 实现的 json 序列化
     */
    fun <T> putJson(
        url: String,
        headers: Map<String, String> = emptyMap(),
        serializer: SerializationStrategy<T>,
        body: T,
        level: HttpLoggingInterceptor.Level = HttpLoggingInterceptor.Level.HEADERS,
        interceptors: List<Interceptor> = emptyList(),
        httpClient: OkHttpClient = HttpClientBuilder.DEFAULT
    ): HttpClient {
        return HttpClient(url, "PUT", httpClient)
            .logLevel(level)
            .headers(headers)
            .applicationJson(serializer, body)
            .interceptors(interceptors)
    }

    /**
     * PATCH 请求
     */
    fun patchJson(
        url: String,
        headers: Map<String, String> = emptyMap(),
        body: Any,
        level: HttpLoggingInterceptor.Level = HttpLoggingInterceptor.Level.HEADERS,
        interceptors: List<Interceptor> = emptyList(),
        httpClient: OkHttpClient = HttpClientBuilder.DEFAULT
    ): HttpClient {
        return HttpClient(url, "PATCH", httpClient)
            .logLevel(level)
            .headers(headers)
            .applicationJson(body)
            .interceptors(interceptors)
    }

    /**
     * PATCH 请求
     *
     * 使用 [kotlinx.serialization](https://github.com/Kotlin/kotlinx.serialization) 实现的 json 序列化
     */
    fun <T> patchJson(
        url: String,
        headers: Map<String, String> = emptyMap(),
        serializer: SerializationStrategy<T>,
        body: T,
        level: HttpLoggingInterceptor.Level = HttpLoggingInterceptor.Level.HEADERS,
        interceptors: List<Interceptor> = emptyList(),
        httpClient: OkHttpClient = HttpClientBuilder.DEFAULT
    ): HttpClient {
        return HttpClient(url, "PATCH", httpClient)
            .logLevel(level)
            .headers(headers)
            .applicationJson(serializer, body)
            .interceptors(interceptors)
    }


    /**
     * DELETE 请求
     */
    fun delete(
        url: String,
        headers: Map<String, String> = emptyMap(),
        level: HttpLoggingInterceptor.Level = HttpLoggingInterceptor.Level.HEADERS,
        interceptors: List<Interceptor> = emptyList(),
        httpClient: OkHttpClient = HttpClientBuilder.DEFAULT
    ): HttpClient {
        return HttpClient(url, "DELETE", httpClient)
            .logLevel(level)
            .headers(headers)
            .interceptors(interceptors)
    }

    /**
     * DELETE 请求
     */
    fun deleteJson(
        url: String,
        headers: Map<String, String> = emptyMap(),
        body: Any,
        level: HttpLoggingInterceptor.Level = HttpLoggingInterceptor.Level.HEADERS,
        interceptors: List<Interceptor> = emptyList(),
        httpClient: OkHttpClient = HttpClientBuilder.DEFAULT
    ): HttpClient {
        return HttpClient(url, "DELETE", httpClient)
            .logLevel(level)
            .headers(headers)
            .applicationJson(body)
            .interceptors(interceptors)
    }

    /**
     * DELETE 请求
     *
     * 使用 [kotlinx.serialization](https://github.com/Kotlin/kotlinx.serialization) 实现的 json 序列化
     */
    fun <T> deleteJson(
        url: String,
        headers: Map<String, String> = emptyMap(),
        serializer: SerializationStrategy<T>,
        body: T,
        level: HttpLoggingInterceptor.Level = HttpLoggingInterceptor.Level.HEADERS,
        interceptors: List<Interceptor> = emptyList(),
        httpClient: OkHttpClient = HttpClientBuilder.DEFAULT
    ): HttpClient {
        return HttpClient(url, "DELETE", httpClient)
            .logLevel(level)
            .headers(headers)
            .applicationJson(serializer, body)
            .interceptors(interceptors)
    }
}